<template>
  <el-dialog
    title="关联角色"
    :visible.sync="visible"
    width="50%"
    top="10vh"
    append-to-body
    :before-close="closeDialogHandle"
    :close-on-click-modal="false"
    class="user-role-modify">

    <el-form inline size="mini" label-width="70px">
      <el-form-item label="用户名称">
        <el-input :value="user.username" readonly></el-input>
      </el-form-item>
      <el-form-item label="状态">
        <el-input :value="user.status | statusFormat " readonly></el-input>
      </el-form-item>
    </el-form>

    <el-row :gutter="20" class="role-box">
      <el-col :span="12">
        <el-card v-loading="roleLoad"
                 element-loading-text="可关联角色列表加载中..."
                 element-loading-spinner="el-icon-loading"
        >
          <div slot="header">
            <span>可关联角色</span>
          </div>
          <div class="search-box">
            <el-input v-model="roleFilterText" clearable size="mini" placeholder="检索可关联角色" @input="roleFilterHandle(300)"></el-input>
          </div>
          <div class="role-list">
            <div v-for="role in showRoleList" :key="role.roleId" class="role">
              <span >{{role.roleName}}</span>
              <span class="simple-name">{{ role.roleKey }}</span>
              <i v-show="role.newRelation" @click="addRoleHandle(role)" class="el-icon-plus role-btn" :class="{'disabled': buttonLoad}"></i>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card v-loading="userRoleLoad"
                 element-loading-text="已关联角色列表加载中..."
                 element-loading-spinner="el-icon-loading"
        >
          <div slot="header">
            <span>已关联角色</span>
          </div>
          <div class="search-box">
            <el-input v-model="userRoleFilterText" clearable size="mini" placeholder="检索已关联角色"
                      @input="userRoleFilterHandle(300)"></el-input>
          </div>
          <div class="role-list">
            <div v-for="role in showUserRoleList"
                 :key="role.roleId"
                 class="role"
            >
              <span :class="{'new-role': role.newRelation}">{{role.roleName}}</span>
              <span class="simple-name">{{role.roleKey}}</span>
              <i @click="subRoleHandle(role)" class="el-icon-minus role-btn" :class="{'disabled': buttonLoad}"></i>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <span slot="footer">
      <el-button @click="closeDialogHandle">关 闭</el-button>
      <el-button :disabled="roleLoad || userRoleLoad || buttonLoad" type="primary" @click="submitHandle">确 定</el-button>
    </span>
  </el-dialog>
</template>

<script>
  export default {
    name: "user-role-modify",
    data() {
      return {
        // 弹出框显示状态[true-显示 false-不显示]
        visible: false,
        // 用户对象
        user: {
          // 用户主键
          userId: undefined,
          // 用户名称
          username: undefined,
          // 用户状态
          status: undefined
        },
        // 可关联角色列表
        roleList: [],
        // 可关联角色列表，页面显示
        showRoleList: [],
        // 可关联角色列表加载状态[true-加载中 false-加载结束]
        roleLoad: false,
        // 可关联角色列表检索内容
        roleFilterText: '',
        // 可关联角色列表检索定时器
        roleFilterTimer: undefined,
        // 已关联角色列表
        userRoleList: [],
        // 已关联角色列表，页面显示
        showUserRoleList: [],
        // 已关联角色列表加载状态[true-加载中 false-加载结束]
        userRoleLoad: false,
        // 已关联角色列表检索内容
        userRoleFilterText: '',
        // 已关联角色列表检索定时器
        userRoleFilterTimer: undefined,
        // 按钮是否可被点击[false-可以被点击 true-不可被点击]
        buttonLoad: false,
      }
    },
    filters: {
      /**
       * 用户状态枚举名称映射
       * @param status 用户状态
       * @return {string} 用户状态名称
       */
      statusFormat(status) {
        switch (status) {
          case 0:
            return '可用'
          case 1:
            return '不可用'
          default:
            return '未知'
        }
      }
    },
    methods: {
      /**
       * 初始化用户关联角色弹出框方法
       * @param {Object} user   用户对象
       */
      initUserRoleModifyDialog(user) {
        let _user = this.user;
        // 初始化用户对象数据
        for (let propKey in _user) {
          _user[propKey] = user[propKey];
        }
        // 打开弹出框
        this.visible = true;

        this.initRoleList();
        this.initUserRoleList();
      },
      /**
       * 初始化可关联角色列表方法
       */
      initRoleList() {
        // 开始数据加载
        this.roleLoad = true;
        this.$axios.$get('/sys/role/list')
          .then( ({ data:roleList }) => {
            // 角色假设是可以关联的
            for (let role of roleList) {
              role.newRelation = true;
            }
            this.roleList = roleList;
            this.showRoleList = roleList;
          })
          .catch(() => {})
          .finally(() => {
            // 数据加载结束
            this.roleLoad = false;
          })
      },
      /**
       * 初始化已关联角色列表方法
       */
      initUserRoleList() {
        // 开始数据加载
        this.userRoleLoad = true;
        this.$axios.$get('/sys/user-role/list', { params: { userId: this.user.userId }})
          .then( ({ data:userRoleList }) => {
            // 用户关联的角色标记为旧角色
            for (let role of userRoleList) {
              role.newRelation = false;
            }
            this.userRoleList = userRoleList;
            this.showUserRoleList = userRoleList;
          })
          .catch(() => {})
          .finally(() => {
            // 数据加载结束
            this.userRoleLoad = false;
          })
      },
      /**
       * 用户关联角色提交事件
       */
      submitHandle() {
        // 按钮禁用
        this.buttonLoad = true;
        let data = {
          userId: this.user.userId,
          roleIds: this.userRoleList.map(_role => _role.roleId),
        }
        this.$axios.$post('/sys/user-role/update', data)
          .then(() => {
            this.notify('success', '操作成功', `’${this.user.username}‘用户关联角色修改成功`)

            this.closeDialogHandle();
          })
          .catch(() => {})
          .finally(() => {
            // 按钮恢复可使用
            this.buttonLoad = false;
          })
      },
      /**
       * 可关联角色列表检索事件
       * @param {number} timeout 延时时长
       */
      roleFilterHandle(timeout) {
        clearTimeout(this.roleFilterTimer);
        this.roleFilterTimer = setTimeout(() => {
          let roleFilterText = this.roleFilterText;
          if (!roleFilterText) {
            this.showRoleList = this.roleList;
          } else {
            // 角色列表过滤
            this.showRoleList = this.roleList.filter(role => role.roleName.indexOf(roleFilterText) !== -1
              || role.simpleName.indexOf(roleFilterText) !== -1);
          }
          clearTimeout(this.roleFilterTimer);
        }, timeout);
      },
      /**
       * 已关联角色列表检索事件
       * @param {number} timeout 延时时长
       */
      userRoleFilterHandle(timeout) {
        clearTimeout(this.userRoleFilterTimer);
        this.userRoleFilterTimer = setTimeout(() => {
          let userRoleFilterText = this.userRoleFilterText;
          if (!userRoleFilterText) {
            this.showUserRoleList = this.userRoleList;
          } else {
            // 角色列表过滤
            this.showUserRoleList = this.userRoleList.filter(role => role.roleName.indexOf(userRoleFilterText) !== -1
              || role.simpleName.indexOf(userRoleFilterText) !== -1);
          }
          clearTimeout(this.userRoleFilterTimer);
        }, timeout);
      },
      /**
       * 新增关联角色事件
       * @param {Object} role 角色对象
       */
      addRoleHandle(role) {
        // 按钮禁用
        this.buttonLoad = true;

        let _userRoleList = this.userRoleList;
        if (_userRoleList.some(_role => _role.roleId === role.roleId)) {
          // 可关联角色列表存储的角色对象变为’不可关联‘状态
          role.newRelation = false;
          this.notify('', '温馨提示', `用户已关联${role.roleName}，不可重复关联`)
          // 按钮恢复可使用
          this.buttonLoad = false;
          return;
        }
        // 新增用户关联的角色
        _userRoleList.unshift(role);
        this.userRoleFilterHandle(0);

        this.roleList = this.roleList.filter(_role => _role.roleId !== role.roleId);
        this.showRoleList = this.showRoleList.filter(_role => _role.roleId !== role.roleId);

        // 按钮恢复可使用
        this.buttonLoad = false;
      },
      /**
       * 减少关联角色事件
       * @param {Object} role 角色对象
       */
      subRoleHandle(role) {
        // 按钮禁用
        this.buttonLoad = true;

        let _roleList = this.roleList;
        let __role = _roleList.find(_role => _role.roleId === role.roleId);
        if (__role) {
          /*
            可关联角色列表和已关联角色列表同时存在该角色
            可关联角色列表存储的角色对象变为’可关联‘状态
           */
          __role.newRelation = true;
        } else {
          role.newRelation = true;
          // 已关联角色列表 转移到 可关联角色列表
          _roleList.unshift(role);
          // 更新显示的可关联角色列表
          this.roleFilterHandle(0)
        }
        // 减少用户关联的角色
        this.userRoleList = this.userRoleList.filter(_role => _role.roleId !== role.roleId);
        this.showUserRoleList = this.showUserRoleList.filter(_role => _role.roleId !== role.roleId);

        // 按钮恢复可使用
        this.buttonLoad = false;
      },
      /**
       * 关闭用户关联角色弹出框事件
       */
      closeDialogHandle() {
        // 关闭弹出框
        this.visible = false;

        let _user = this.user;
        // 清空用户对象数据
        for (let propKey in _user) {
          _user[propKey] = undefined;
        }
        this.roleList = [];
        this.showRoleList = [];
        this.roleFilterText = '';
        clearTimeout(this.roleFilterTimer)
        this.roleFilterTimer = undefined;
        this.userRoleList = [];
        this.showUserRoleList = [];
        this.userRoleFilterText = '';
        clearTimeout(this.userRoleFilterTimer)
        this.userRoleFilterTimer = undefined;
      }
    }
  }
</script>

<style scoped>
  .user-role-modify >>> .el-dialog__body {
    padding: 20px;
  }
  .role-box >>> .el-card__header {
    padding: 10px 20px;
  }
  .role-box .search-box {
    margin-bottom: 10px;
  }
  .role-box .role-list {
    height: 350px;
    max-height: 350px;
    overflow-y: scroll;
  }
  .role-box .role-list .role {
    line-height: 30px;
    position: relative;
  }
  .role-box .role-list .role .new-role {
    color: #71e2a3;
  }
  .role-box .role-list .role .simple-name {
    color: #C0C4CC;
  }
  .role-box .role-list .role .role-btn {
    position: absolute;
    right: 10px;
    cursor: pointer;
    font-size: 17px;
    line-height: 30px;
  }
  .role-box .role-list .role .role-btn.disabled {
    pointer-events: none;
  }
  .role-box .role-list .role .role-btn:hover {
    color: #71e2a3;
  }
</style>
